﻿<!DOCTYPE html>
<html>
<head>
    <title>Products</title>
    <style type="text/css">
        body {
            color: #444444;
            font-family: Calibri, Verdana;
        }

        .titleSpan {
            font-weight: bold;
        }

        .sectionArea {
            border: 1px solid gainsboro;
            padding: 8px;
            margin-bottom: 8px;
            background-color: #f1edb9;
            width: 50%;
        }

        .ideaBox {
            cursor: pointer;
            padding-top: 8px;
        }

        #modelArea {
            border: 1px solid gainsboro;
            padding: 8px;
            margin-bottom: 8px;
        }

        button, input, textarea {
            font-family: Calibri, Verdana;
            font-size: 100%;
        }
    </style>
</head>
<body>

    <h1>Products</h1>
    <p>
        This page shows how to create / read / update / delete information from a LightSwitch OData service.
    </p>
    <div id="messageBar" class="sectionArea"></div>
    <button id="refreshButton" data-bind="click: loadproducts, disable: communicating">Refresh</button>
    <div id="productsArea"
         data-bind="template: { name: 'productTemplate', foreach: test }"
         class="sectionArea">
    </div>

    <script type="x-jquery-tmpl" id="productTemplate">
        <div class='productBox'>

            {{if editing}}
            <input type="text" data-bind="value: Title" size="80" /><br />
            <textarea data-bind="value: Title" cols="80" rows="4"></textarea><br />
            <input type="text" data-bind="value: Title" size="80" /><br />
            <button data-bind="click: saveproduct, disable: communicating">Save</button>
            {{else}}<br />
            <span class='titleSpan'>${Title}</span><br />
            ${Title}<br />
            $${Title}<br />
            <button data-bind="click: editproduct, disable: communicating">Edit</button>
            {{/if}}
            <button data-bind="click: deleteproduct, disable: communicating">Delete</button>
            <br />
        </div>
    </script>

    <div id='newproductArea' class="sectionArea">
        <strong>Title:</strong><br />
        <input data-bind="value: newproduct.productName" /><br />
        <strong>Description:</strong><br />
        <textarea data-bind="value: newproduct.description"></textarea><br />
        <strong>Price:</strong><br />
        <input data-bind="value: newproduct.price" /><br />
        <button id="addproduct" data-bind="click: addNewproduct, disable: communicating">Add New product</button><br />
    </div>

    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>

    <!-- Get this from https://github.com/SteveSanderson/knockout/downloads. -->
    <script type="text/javascript" src="JavaScript/knockout-1.2.1.js"></script>
    <!--<script type='text/javascript' src="JavaScript/knockout-3.1.0.js"></script> -->
    <script type="text/javascript" src="JavaScript/knockout_mapping-latest.js"></script>
    <script type="text/javascript" src="JavaScript/datajs-1.1.2.js"></script>
    <script type="text/javascript" src="JavaScript/json2.js"></script>

    <script type="text/javascript">
        // Root URI for the service.
        //config.EnableCors(new EnableCorsAttribute("*", "*", "*", "DataServiceVersion, MaxDataServiceVersion"));
        var serviceUri = "./ApplicationData.svc/";

        // This is what our view model looks like.
        var productsViewModelFn = function () {
            var that = this;

            // The list of products we are editing.
            this.test = ko.observableArray([]);

            // A placeholder for a new product to be added.
            this.newproduct = {
                id: ko.observable("0"),
                productName: ko.observable("New product"),
                description: ko.observable("Product description"),
                price: ko.observable("0.00")
            };

            // A flag indicating whether we are communicating with the server.
            this.communicating = ko.observable(false);

            // Adds the newproduct placeholder to the list and saves to the server.
            this.addNewproduct = function () {
                var request = {
                    requestUri: serviceUri + "Breeds",
                    Accept: "application/json",
                    method: "POST",
                    data: {
                        Id: that.newproduct.id(),
                        ProductName: that.newproduct.productName(),
                        Description: that.newproduct.description(),
                        Price: that.newproduct.price()
                    }
                };
                makeRequest(request, function (newItem) {
                    that.newproduct.id("Id");
                    that.newproduct.productName("New product");
                    that.newproduct.description("Product description");
                    that.newproduct.price("Price");

                    that.products.push(productModelToViewModel(newItem));
                });
            };

            // Discards all products and reloads them from the server.
            this.loadproducts = function () {
                makeRequest({ requestUri: serviceUri + "Breeds" }, function (data) {
                    that.test().splice(0, productsViewModel.test().length);

                    //$.each(data.results, function (index, value) {
                    //    that.test.push(productModelToViewModel(value));
                    //});
                });
            };
        };

        var productsViewModel = new productsViewModelFn();

        // Map from a server model object to a view model with functions and flags.
        var productModelToViewModel = function (model) {
            // Deletes this product from the server and removes it from the view model.
            model.deleteproduct = function () {
                var that = this;
                var request = {
                    requestUri: that.__metadata.uri(),
                    headers: { "If-Match": " *" },
                    method: "DELETE"
                };
                makeRequest(request, function (data) {
                    productsViewModel.products.remove(that);
                });
            };

            // Start editing an product.
            model.editproduct = function () {
                this.editing(true);
            };

            // Save the changes to the product.
            model.saveproduct = function () {
                var that = this;
                var data = productViewModelToModel(that);
                var request = {
                    requestUri: data.__metadata.uri,
                    headers: { "If-Match": " *" },
                    method: "PUT",
                    data: data
                };
                makeRequest(request, function (data) {
                    that.editing(false);
                });
            };

            model.editing = false;

            var result = ko.mapping.fromJS(model);

            // Propagate the 'communicate' to simplify binding.
            result.communicating = ko.dependentObservable(function () {
                return productsViewModel.communicating();
            }, productsViewModel);

            return result;
        };

        // Map from a view model back to a server object.
        var productViewModelToModel = function (viewModel) {
            var result = ko.mapping.toJS(viewModel);
            delete result.editing;
            return result;
        };

        // Make a request, setting the 'communicating' flag.
        var makeRequest = function (request, success) {
            productsViewModel.communicating(true);
            $("#messageBar").text("Contacting server...").show();
            return OData.request(request, function (data) {
                productsViewModel.communicating(false);
                $("#messageBar").hide();
                success(data);
            }, function (err) {
                productsViewModel.communicating(false);
                $("#messageBar").hide();
                alert("Error while contacting server: " + err.message);
            });
        };

        // Bind the model to everything in the document that needs it.
        ko.applyBindings(productsViewModel);

        // Start loading products asynchronously.
        productsViewModel.loadproducts();

    </script>
</body>
</html>
